; 整合菜单程序 - 日期和时间实验（删除二号功能）
include 9004.mac   ; 包含宏定义
.model small
.stack 100h

.data
; 菜单选项
menu_title db 'Date and Time Experiments Menu', 0dh, 0ah, '=======================', 0dh, 0ah, '$'
menu1 db '1) Display Date and Time in Windows', 0dh, 0ah, '$'
menu3 db '2) Real-time Clock Display', 0dh, 0ah, '$'
menu4 db '3) 60-second Countdown Timer', 0dh, 0ah, '$'
menu_exit db '0) Exit Program', 0dh, 0ah, '$'
prompt_choice db 'Enter your choice: $'

; 日期和时间变量
years  dw ?
month db ?		
day db ?
week db ?
hour db ?
minutes db ?
seconds db ?
persec db ?
time1 db ?
time2 db ?
n db 4

; 倒计时变量
countdown db 60
timer_active db 0

; 显示文本
letter1 db 'Date and week=  ','$' 
letter2 db 'Time=  ','$'
countdown_msg db 'Countdown: $'
bell db 07h, '$'  ; 响铃字符

.code
main proc
    mov ax, @data
    mov ds, ax
    
main_menu:
    clearsc   ; 清屏
    cursor 5, 30  ; 设置菜单位置
    
    ; 显示菜单
    mov ah, 9
    lea dx, menu_title
    int 21h
    lea dx, menu1
    int 21h
    lea dx, menu3
    int 21h
    lea dx, menu4
    int 21h
    lea dx, menu_exit
    int 21h
    
    ; 获取用户选择
    cursor 12, 30
    lea dx, prompt_choice
    int 21h
    
    mov ah, 1
    int 21h
    
    ; 修复跳转超出范围问题：使用短跳转+长跳转组合
    cmp al, '1'
    jne not1       ; 使用短跳转到下一个比较点
    jmp option1    ; 使用长跳转到目标
not1:
    cmp al, '2'
    jne not2
    jmp option3
not2:
    cmp al, '3'
    jne not3
    jmp option4
not3:
    cmp al, '0'
    jne not0
    jmp exit_program
not0:
    jmp main_menu  ; 无效输入返回菜单

option1:  ; 在不同窗口中显示日期和时间
    clearsc
    clearsw 5, 20, 8, 60, 1Fh  ; 蓝底白字窗口
    cursor 6, 22
    call display_datetime
    jmp wait_key

option3:  ; 显示变化的时间
    clearsc
    cursor 12, 35
    mov ah, 2
    mov dl, ' '
    int 21h
    
    real_time_loop:
        mov n, 4  ; 每次循环重置n值
        cursor 12, 35
        call display_time
        
        ; 检查按键
        mov ah, 1
        int 16h
        jz real_time_loop  ; 无按键继续
        
        ; 有按键则返回
        mov ah, 0  ; 清除键盘缓冲区
        int 16h
        jmp main_menu

option4:  ; 60秒倒计时
    clearsc
    clearsw 10, 30, 14, 50, 4Fh  ; 红底白字
    mov countdown, 60
    
    countdown_loop:
        cursor 12, 35
        lea dx, countdown_msg
        mov ah, 9
        int 21h
        
        mov bl, countdown
        mov bh, 0
        call disp_2_10
        
        ; 每秒递减
        mov cx, 000Fh
        mov dx, 4240h  ; 1秒延迟 (1,000,000微秒)
        mov ah, 86h
        int 15h
        
        dec countdown
        jz end_countdown
        
        ; 检查退出键
        mov ah, 1
        int 16h
        jz countdown_loop  ; 无按键继续倒计时
        jmp main_menu      ; 有按键返回主菜单
        
    end_countdown:
        ; 时间到响铃
        lea dx, bell
        mov ah, 9
        int 21h
        jmp wait_key

wait_key:
    mov ah, 0
    int 16h
    jmp main_menu

exit_program:
    mov ah, 4Ch
    int 21h
main endp

; 显示时间 (HH:MM:SS)
display_time proc
    push ax
    push bx
    push cx
    push dx
    
    mov al, n  ; n=4、2、0，为时、分、秒单元地址
    out 70h, al  ; 输出到地址口
    in al, 71h  ; 从数据口读取小时、分、秒
    mov ah, al  ; al=压缩BCD码，如15点00010101
    mov cl, 4
    shr ah, cl  ; ah右移4位，高4位→低4位00000001
    add ah, 30h  ; ASCII码
    and al, 0fh  ; 保留个位数
    add al, 30h  ; ASCII码
    mov time1, ah
    mov time2, al
    displ time1  ; 显示十位
    displ time2  ; 显示个位
    sub n, 2  ; 下一个地址
    js exit
    
    displ ':'  ; 显示:

lll:
mov al,n					;n=4、2、0，为时、分、秒单元地址	
out 70h,al				  ;输出到地址口
in al,71h				   ;从数据口读取小时、分、秒
mov ah,al				   ;al=压缩BCD码，如15点00010101
mov cl,4
shr ah,cl				   ;ah右移4位，高4位→低4位00000001
add ah,30h				  ;ASCII码
and al,0fh				  ;保留个位数
add al,30h				  ;ASCII码
mov time1,ah
mov time2,al
displ time1				 ;显示十位
displ time2				 ;显示个位
sub n,2				  ;下一个地址
js exit
displ ':'				   ;显示:

jmp lll						

exit:
    pop dx
    pop cx
    pop bx
    pop ax
    ret  ; 仅返回，不退出程序
display_time endp

; 显示日期和时间
display_datetime proc
    ; 读取并显示日期
    mov ah, 2Ah
    int 21h
    mov years, cx
    mov month, dh
    mov day, dl
    mov week, al
    
    lea dx, letter1
    mov ah, 9
    int 21h
    
    mov bx, years
    call disp_2_10
    displ '/'
    
    mov bl, month
    mov bh, 0
    call disp_2_10
    displ '/'
    
    mov bl, day
    mov bh, 0
    call disp_2_10
    displ ' '
    
    mov bl, week
    mov bh, 0
    call disp_2_10
    
    ; 读取并显示时间
    enter
    lea dx, letter2
    mov ah, 9
    int 21h
    
    ; 使用新的时间显示方法
    call display_time
    ret
display_datetime endp

; 二进制转十进制显示子程序 (同9004.asm)
disp_2_10 proc
    push ax
    push bx
    push cx
    push dx
    mov ax, bx
    mov cx, 0
    mov bx, 10
let1:
    mov dx, 0
    inc cx
    idiv bx
    push dx
    cmp ax, 0
    jnz let1
let2:
    pop ax
    add ax, 0030h
    mov dl, al
    mov ah, 2
    int 21h
    loop let2
    pop dx
    pop cx
    pop bx
    pop ax
    ret
disp_2_10 endp

end main